﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EventBusSharp
{
    public class EventBus
    {
        private List<CallBacks> list;
        private List<StrCallBacks> strlist;

        /// <summary>
        /// 单例，防止实例化
        /// </summary>
        private EventBus()
        {
            list = new List<CallBacks>();
            strlist = new List<StrCallBacks>();
        }

        private static EventBus _instance;
        /// <summary>
        /// 获取实例
        /// </summary>
        public static EventBus Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new EventBus();
                    return _instance;
                }
                return _instance;
            }
        }

        /// <summary>
        /// 订阅消息，obj这个对象订阅T这个消息，发布消息时调用回调方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="callBackFunc"></param>
        public void Subscribe<T>(object obj, Action<T> callBackFunc) where T : IEvent
        {

            try
            {
                //判断有没有注册过,注册过就不能再注册。疑惑点，一个类中多次注册行不行？？
                if (list.Any(it => it.Subscriber == obj && it.EventType == typeof(T)))
                {
                    return;
                }
                list.Add(new CallBacks
                {
                    Subscriber = obj,
                    EventType = typeof(T),
                    Action = new Action<object>(o => callBackFunc((T)o))
                });
            }
            catch (Exception ex)
            {
            }
        }

        /// <summary>
        /// 取消订阅，obj这个对象取消订阅T这个消息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        public void UnSubscribe<T>(object obj) where T : IEvent
        {

            try
            {
                list.RemoveAll(it => it.Subscriber == obj && it.EventType == typeof(T));
            }
            catch (Exception ex)
            {
            }
        }


        /// <summary>
        /// 发布消息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        public void Publish<T>(T data) where T : IEvent
        {
            list.Where(it => it.EventType == typeof(T)).ToList().ForEach(it =>
            {
                try
                {
                    it.Action(data);
                }
                catch (Exception ex)
                {

                }
            });
        }


        public void Subscribe(object obj, string eventName, Action<string> callBackFunc)
        {
            try
            {
                //判断有没有注册过,注册过就不能再注册。疑惑点，一个类中多次注册行不行？？
                if (strlist.Any(it => it.Subscriber == obj && it.EventName == eventName))
                {
                    return;
                }
                strlist.Add(new StrCallBacks
                {
                    Subscriber = obj,
                    EventName = eventName,
                    Action = callBackFunc
                });
            }
            catch (Exception ex)
            {
            }
        }

        public void UnSubscribe(object obj, string eventName)
        {
            try
            {
                strlist.RemoveAll(it => it.Subscriber == obj && it.EventName == eventName);
            }
            catch (Exception ex)
            {
            }
        }
        public void Publish(string eventName, string data)
        {
            try
            {
                strlist.Where(it => it.EventName == eventName).ToList().ForEach(it =>
                {
                    it.Action(data);
                });
            }
            catch (Exception ex)
            {

            }
        }
        /// <summary>
        /// 内部类
        /// </summary>
        class CallBacks
        {
            /// <summary>
            /// T的类型
            /// </summary>
            public Type EventType { get; set; }

            /// <summary>
            /// 谁订阅对象
            /// </summary>
            public object Subscriber { get; set; }

            public Action<object> Action { get; set; }
        }

        class StrCallBacks
        {
            /// <summary>
            /// T的类型
            /// </summary>
            public string EventName { get; set; }

            /// <summary>
            /// 谁订阅对象
            /// </summary>
            public object Subscriber { get; set; }

            public Action<string> Action { get; set; }
        }
    }

    public interface IEvent { }
}